﻿using System;
using System.Collections;

namespace TextEditor
{
   

    public class A_ContentChangeLog : A_Action
    {
        internal bool CanLog = true;
        internal ZYTextContainer Container = null;
        internal int index = 0;
        private ArrayList myUndoSteps = new ArrayList();
        public string strUndoName = null;

        public override string ActionName()
        {
            return "log";
        }

        public override A_Action Clone()
        {
            return this;
        }

        public override bool isEnable()
        {
            return (this.myUndoSteps.Count > 0);
        }

        public override bool isUndoable()
        {
            return true;
        }

        public void LogAdd(ZYTextElement NewElement)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.Style = 2;
                step.Element = NewElement;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogAddRang(ArrayList myList)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.Elements = myList;
                step.Style = 5;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogAttribute(ZYTextElement vElement, ZYAttribute vAttribute, object NewValue)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.Element = vElement;
                step.Attribute = vAttribute;
                step.OldValue = vAttribute.Value;
                step.NewValue = NewValue;
                step.Style = 4;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogInsert(int index, ZYTextElement NewElement)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.index = index;
                step.Element = NewElement;
                step.Style = 0;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogInsertRange(int index, ArrayList myList)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.index = index;
                step.Elements = myList;
                step.Style = 1;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogRemove(int index, ZYTextElement myElement)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.Style = 3;
                step.index = index;
                step.Element = myElement;
                this.myUndoSteps.Add(step);
            }
        }

        public void LogRemoveRange(int index, ArrayList myList)
        {
            if (this.CanLog)
            {
                UndoStep step = new UndoStep();
                step.Elements = new ArrayList();
                step.Elements.AddRange(myList);
                step.index = index;
                step.Style = 6;
                this.myUndoSteps.Add(step);
            }
        }

        public override bool Redo()
        {
            try
            {
                bool flag = false;
                int index = -1;
                ZYTextElement element = null;
                if (this.myUndoSteps.Count <= 0)
                {
                    return false;
                }
                foreach (UndoStep step in this.myUndoSteps)
                {
                    switch (step.Style)
                    {
                        case 0:
                            {
                                flag = true;
                                this.Container.ChildElements.Insert(step.index, step.Element);
                                step.Element.OwnerDocument = this.Container.OwnerDocument;
                                step.Element.Parent = this.Container;
                                element = step.Element;
                                continue;
                            }
                        case 1:
                            {
                                flag = true;
                                this.Container.ChildElements.InsertRange(step.index, step.Elements);
                                if (step.Elements.Count > 0)
                                {
                                    element = (ZYTextElement)step.Elements[0];
                                }
                                continue;
                            }
                        case 2:
                            {
                                flag = true;
                                this.Container.ChildElements.Add(step.Element);
                                element = step.Element;
                                continue;
                            }
                        case 3:
                            {
                                flag = true;
                                index = step.index;
                                this.Container.ChildElements.Remove(step.Element);
                                continue;
                            }
                        case 4:
                            {
                                step.Attribute.SetValue(step.NewValue);
                                step.Element.RefreshSize();
                                element = step.Element;
                                step.Element.UpdateAttrubute();
                                continue;
                            }
                        case 5:
                            {
                                flag = true;
                                this.Container.ChildElements.AddRange(step.Elements);
                                if (step.Elements.Count > 0)
                                {
                                    element = (ZYTextElement)step.Elements[0];
                                }
                                continue;
                            }
                        case 6:
                            {
                                flag = true;
                                index = step.index;
                                this.Container.ChildElements.RemoveRange(step.index, step.Elements.Count);
                                continue;
                            }
                    }
                }
                if (flag)
                {
                    base.OwnerDocument.RefreshElements();
                }
                base.OwnerDocument.RefreshSize();
                base.OwnerDocument.RefreshLine();
                base.OwnerDocument.UpdateView();
                if (element != null)
                {
                    base.myOwnerDocument.Content.CurrentElement = element;
                }
                else if (index >= 0)
                {
                    base.myOwnerDocument.Content.MoveSelectStart(index);
                }
                return true;
            }
            catch
            {
            }
            return true;
        }

        public override bool Undo()
        {
            ZYTextElement element = null;
            int index = -1;
            bool flag = false;
            if (this.myUndoSteps.Count > 0)
            {
                for (int i = this.myUndoSteps.Count - 1; i >= 0; i--)
                {
                    UndoStep step = (UndoStep) this.myUndoSteps[i];
                    switch (step.Style)
                    {
                        case 0:
                            flag = true;
                            index = step.Element.Index;
                            this.Container.ChildElements.Remove(step.Element);
                            break;

                        case 1:
                            flag = true;
                            foreach (ZYTextElement element3 in step.Elements)
                            {
                                index = element3.Index;
                                this.Container.ChildElements.Remove(element3);
                            }
                            break;

                        case 2:
                            flag = true;
                            index = step.Element.Index;
                            this.Container.ChildElements.Remove(step.Element);
                            break;

                        case 3:
                            flag = true;
                            this.Container.ChildElements.Insert(step.index, step.Element);
                            element = step.Element;
                            break;

                        case 4:
                            step.Attribute.SetValue(step.OldValue);
                            step.Element.UpdateAttrubute();
                            step.Element.RefreshSize();
                            element = step.Element;
                            break;

                        case 5:
                            flag = true;
                            foreach (ZYTextElement element2 in step.Elements)
                            {
                                index = element2.Index;
                                this.Container.ChildElements.Remove(element2);
                            }
                            break;

                        case 6:
                            flag = true;
                            this.Container.ChildElements.InsertRange(step.index, step.Elements);
                            index = step.index;
                            break;
                    }
                }
                if (flag)
                {
                    base.myOwnerDocument.RefreshElements();
                }
                base.OwnerDocument.RefreshSize();
                base.myOwnerDocument.RefreshLine();
                base.myOwnerDocument.UpdateView();
                return true;
            }
            return false;
        }

        public override string UndoName()
        {
            return this.strUndoName;
        }

        private class UndoStep
        {
            internal ZYAttribute Attribute;
            internal ZYTextElement Element;
            internal ArrayList Elements;
            internal int index;
            internal object NewValue;
            internal object OldValue;
            internal int Style = 0;
        }
    }
}

